/*******************************************
 * Copyright 2007 Aphrodite Framework for javaME .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * Email : owner@aphroditeme.dev.java.net
 * Contributors:
 *     Kent Elton - initial API and implementation
 *******************************************/

package com.aphrodite.ui.widgets;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;

import com.aphrodite.util.StringUtil;
import com.aphrodite.util.geom.GeomUtil;

/**
 * A text area that cannot be edited
 * 
 * @author kentelt
 * 
 */
public final class StaticTextArea extends TraversableWidget {

	private static final int SCROLL_STEP = 25;
	private int borderWidth = 1;
	private int currentY = 0;
	private int innerHeight = 0;
	private int innerWidth = 0;
	private int interline = 2;
	private int padding = 1;
	private int prevY;
	// private int scrollbarColor = 0x7B0000;
	private int scrollbarHeight = 0;
	private int scrollbarTop = 0;

	private int scrollbarWidth = 4;
	private String text;
	private int textHeight = 0;
	private String[] textRows = null;
	private boolean canScroll = true;

	public StaticTextArea(Theme theme, String text, int width, int height) {
		super(theme, width, height);
		this.innerWidth = width - 2 * borderWidth - 2 * padding - scrollbarWidth;
		this.innerHeight = height - 2 * borderWidth - 2 * padding;
		this.text = text;
		updateModel();
	}

	public void cleanUp() {
		textRows = null;
		text = null;
	}

	public String getText() {
		return text;
	}

	/**
	 * Adjust the widget's dimensions to show the entire contents. *
	 * <p>
	 * Triggers a stateChanged event
	 * </p>
	 * 
	 * @see StateListener
	 */
	public void resizeToFit() {
		this.height = textHeight;
		this.width = width < 100 ? 100 : width;
		canScroll = false;
		updateModel();
		stateChanged(this);
	}

	public boolean moveDown() {
		scroll(SCROLL_STEP);
		return true;
	}

	public boolean moveUp() {
		scroll(-SCROLL_STEP);
		return true;
	}

	public boolean pointerDrag(int px, int py) {
		if (isVisible && GeomUtil.withinBounds(px, py, x, y, width, height)) {
			if (py < prevY) {
				scroll(SCROLL_STEP);
			} else {
				scroll(-SCROLL_STEP);
			}
			return true;
		}
		return false;
	}

	public boolean pointerPress(int px, int py) {
		if (isVisible && GeomUtil.withinBounds(px, py, x, y, width, height)) {
			prevY = py;
			return true;
		}
		return false;
	}

	public void render(Graphics g) {
		if (!isVisible)
			return;
		capture(g, width, height, true);
		g.setColor(theme.fgColor);
		g.setFont(theme.widgetFont);
		g.translate(borderWidth + padding, borderWidth + padding);
		if (textRows != null) {
			for (int i = 0; i < textRows.length; i++) {
				g.drawString(textRows[i], 0, i * (theme.widgetFont.getHeight() + interline) - currentY, Graphics.TOP
						| Graphics.LEFT);
			}
		}
		if (canScroll) {
			g.setColor(Theme.baseCmpColor);
			g.fillRect(innerWidth, scrollbarTop, scrollbarWidth, scrollbarHeight);
		}
		g.translate(-(borderWidth + padding), -(borderWidth + padding));
		release(g, width, height, true);
	}

	private void scroll(int delta) {
		if (canScroll) {
			currentY += delta;
			if (currentY < 0) {
				currentY = 0;
			} else if (currentY > textHeight - innerHeight) {
				currentY = Math.max(0, textHeight - innerHeight);
			}
			scrollbarTop = innerHeight * currentY / textHeight;
			reDrawWidget();
		}
	}

	public void setText(String text) {
		this.text = text;
		updateModel();
	}

	protected boolean traverse(int dir, int viewportWidth, int viewportHeight, int[] visRect_inout) {
		switch (dir) {
		case Canvas.DOWN:
			if (location == IN) {
				moveDown();
			} else if (location == UPPER) {
				location = IN;
			} else {
				return false;
			}
			break;
		case Canvas.UP:
			if (location == IN) {
				moveUp();
			} else if (location == LOWER) {
				location = IN;
			} else {
				return false;
			}
			break;
		case Canvas.LEFT:
			location = UPPER;
			return false;
		case Canvas.RIGHT:
			location = LOWER;
			return false;
		default:
			return false;
		}
		return true;
	}

	protected void updateModel() {
		textRows = StringUtil.doTextWrap(text, theme.widgetFont, innerWidth, innerWidth);
		this.textHeight = textRows.length * (interline + theme.widgetFont.getHeight());
		scrollbarHeight = Math.min(innerHeight, innerHeight * innerHeight / textHeight);
		scrollbarTop = 0;
		currentY = 0;
		reDraw();
		stateChanged(this);

	}
}
